
//!============================================================================
//!<Interface> Vertex|Fragment
//!----------------------------------------------------------------------------

//!<Include> StdDirLight.sl
//!<Include> StdPosLight.sl
//!<Include> StdSpotLight.sl

//!<Include> ILightModel.sl

#if !defined(MaxDirLights)
#define MaxDirLights	4
#endif

#if !defined(MaxPointLights)
#define MaxPointLights	6
#endif

#if !defined(MaxSpotLights)
#define MaxSpotLights	6
#endif

// Enabled directional lights
uniform StdDirLight ds_StdDirLights[MaxDirLights];
// Enabled directional lights count
uniform int ds_StdDirLightsCount = 0;

// Enabled directional lights
uniform StdPointLight ds_StdPointLights[MaxPointLights];
// Enabled point lights count
uniform int ds_StdPointLightsCount = 0;

// Enabled directional lights
uniform StdSpotLight ds_StdSpotLights[MaxSpotLights];
// Enabled spot lights count
uniform int ds_StdSpotLightsCount = 0;

// Standard light model definition
struct StdLightModel {
	// Light model ambient color factor
	vec4 Ambient;
};

// Current light model
uniform StdLightModel ds_LightModel = StdLightModel(
	vec4(0.2, 0.2, 0.2, 1.0)
	);

// Current material state
uniform StdMaterial ds_Material = StdMaterial(
	vec4(0.0, 0.0, 0.0, 0.0),	// Emission
	vec4(0.0, 0.0, 0.0, 0.0),	// Ambient
	vec4(1.0, 1.0, 1.0, 1.0),	// Diffuse
	vec4(0.0, 0.0, 0.0, 0.0),	// Specular
	0.0							// Shiness
	);

//!============================================================================
//!<Source> Vertex|Fragment
//!----------------------------------------------------------------------------

//<Include> Interface

vec4 ComputeLightsContribution(vec4 vPosition, vec3 vNormal)
{
	StdLightColor lColors = StdLightColor(
		vec4(0.0, 0.0, 0.0, 0.0),	// Ambient
		vec4(0.0, 0.0, 0.0, 0.0),	// Diffuse
		vec4(0.0, 0.0, 0.0, 0.0)	// Specular
		);
	vec3 ePosition = vPosition.xyz / vPosition.w;
	vec3 eye = vec3(0.0, 0.0, 1.0);
	int i;

#if defined(LightModelLocalViewer)
	// Local viewer computation
	eye = -normalize(ePosition);
#endif

	// Contribute every directional light
	for (i = 0; i < ds_StdDirLightsCount; i++) {
		// Compute light contribution
		ComputeLightContribution(lColors, ds_StdDirLights[i], vNormal, ds_Material.Shininess);
	}
	// Contribute every positional light
	for (i = 0; i < ds_StdPointLightsCount; i++) {
		// Compute light contribution
		ComputeLightContribution(lColors, ds_StdPointLights[i], vNormal, eye, ePosition, ds_Material.Shininess);
	}
	// Contribute every spot light
	for (i = 0; i < ds_StdSpotLightsCount; i++) {
		// Compute light contribution
		ComputeLightContribution(lColors, ds_StdSpotLights[i], vNormal, eye, ePosition, ds_Material.Shininess);
	}

	// Final color computation
	return (
		ds_LightModel.Ambient +							// Light model ambient contribution
		ds_Material.Ambient * lColors.Ambient +			// Ambient contribution
		ds_Material.Diffuse * lColors.Diffuse +			// Diffuse contribution
		ds_Material.Specular * lColors.Specular			// Specular contribution
		);
}
